﻿using BaseUtils.Helper;
using BaseUtils.Logger;
using Core.UserScript;
using MyMes.Mes;
using NW_WEB_Service.com.app.entities;
using NW_WEB_Service.com.app.entities.modal;
using NWMES.Mes;
using NWMES.Model;
using Service.src.Base;
using Service.src.Flow.JavaScript;
using Service.src.Model.Folw;
using Service.src.NW.Enum;
using Service.src.NW.Model;
using Service.src.NW.Model.Folw;
using Service.src.NW.Processor.Core;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Service.src.Flow.Server
{
    public class FlowServer : FlowProcessor
    {

        /// <summary>
        /// 添加流程节点
        /// </summary>
        /// <param name="FolwId"></param>
        /// <param name="NodeHubId"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <returns></returns>
        public string AddNode(NodeVO Node)
        {
            AppData.RemoveOpenFlow(Node.FlowId);
            FlowRoot Flow = FlowProcessor.GetFlow(Node.FlowId);
            if (Flow == null)
            {
                LoggerService.Error($"添加流程节异常：找不到流程，流程id：{Node.FlowId}，节点信息:{Node.ToJson()}");
                return null;
            }
            NodeProcessor NodeItem = ConvertHelper.ToObject<NodeProcessor>(ConvertHelper.ToJson(ComponentHelper.GetNode(Node.NodeHubId)));
            NodeItem.id = FlowNode.GeneratedId(Flow);
            NodeItem.label = NodeItem.name;
            Rect rect = new Rect();
            rect.x = Node.X;
            rect.y = Node.Y;
            rect.w = NodeItem.style.width;
            rect.h = NodeItem.style.height;
            NodeItem.rect = rect;
            NodeItem.style = NodeItem.style;
            NodeItem.enable = 1;

            if (Flow == null)
            {
                Flow = new FlowRoot();
                Flow.Id = AppData.OpenFlows.Count + 1;
                Flow.processors = new List<NodeProcessor> { NodeItem };
            }
            else
            {
                Flow.processors.Add(NodeItem);
            }
            UpdateFlow(Flow);

            string ss = Flow.ToJson(new[] { "Children", "Parents" });
            SetNodeItemInitValue(NodeItem);
            return ss;
        }

        private void SetNodeItemInitValue(NodeProcessor nodeItem)
        {
            switch (nodeItem.Group)
            {
                case GroupTypeEnum.MES:
                    MESBaseService Service = new MESBaseService();
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MiFindCustomAndSfcData)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiFindCustomAndSfcData.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MachineIntegration)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MachineIntegration.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MiReleaseSfcWithActivity)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiReleaseSfcWithActivity.Params);
                    }
                    //if (nodeItem.nodeType == NodeTypeEnum.MES_MiAssembleComponentsToSfcsServiceService)
                    //{
                    //    Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiAssembleComponentsToSfcs.Params);
                    //}
                    if (nodeItem.nodeType == NodeTypeEnum.MES_miCheckBOMInventory)
                    {
                        //Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiChec.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_miAssembleAndCollectDataForSfc)
                    {
                        //Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiFindCustomAndSfcData.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MiGetCustomerBarcodeDataServiceService)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MESGetCustomerBarcodeData.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_DataCollectForResourceFAIServiceService)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", DataCollectForResourceFAIService.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MiCheckInventoryAttributes)
                    {
                        //Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiFindCustomAndSfcData.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MiAssembleComponentsToSfc)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MiAssembleComponentsToSfcs.Params);
                    }
                    if (nodeItem.nodeType == NodeTypeEnum.MES_MiModuleAutoInSet)
                    {
                        Service.UpdateMesRequestParams($"{nodeItem.id}_{nodeItem.nodeType}", MesModuleAutoInSet.Params);
                    }
                    break;
            }
        }

        public void sfsdf(IMesBaseEntity s, IMesBaseEntity de)
        {
            de.Url = s.Url;
        }

        /// <summary>
        /// 更新流程节点
        /// </summary>
        /// <param name="FolwId"></param>
        /// <param name="NodeItemJson"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public string UpdateFlowNode(long FlowId, string NodeItemJson)
        {
            // AppData.RemoveOpenFlow(FlowId);
            List<FlowNode> UpdateNode = ConvertHelper.ToObject<List<FlowNode>>(NodeItemJson);
            if (UpdateNode == null || UpdateNode.Count <= 0)
            {
                throw new Exception("");
            }
            FlowRoot Flow = FlowProcessor.GetFlow(FlowId);
            int Index = 0;
            foreach (FlowNode Item in UpdateNode)
            {
                Index = Flow.processors.FindIndex((no) => no.id == Item.id);
                if (Index < 0)
                {
                    continue;
                }
                //Flow.processors[Index].label = Item.name;
                Flow.processors[Index].rect = Item.rect;
                Console.WriteLine(Item.rect.ToJson());
            }
            if (Index < 0)
            {
                return Flow.ToJson(new[] { "Children", "Parents" });
            }
            FlowProcessor.UpdateFlow(Flow);
            if (AppData.OpenFlows.ContainsKey(FlowId))
            {
                AppData.OpenFlows[FlowId] = Flow;
            }
            // Flow = FlowProcessor.GetFlow(FolwName);
            string s = Flow.ToJson(new[] { "Children", "Parents" });
            //dynamic fsd = NodeBaseScript.GetValue(s, "name");
            return s;
        }

        public string DeleteFlowNode(long FlowId, string _NodeIds, string _LinkIds)
        {
            AppData.RemoveOpenFlow(FlowId);
            FlowRoot Flow = FlowProcessor.GetFlow(FlowId);
            List<int> NodeIds = new List<int>();
            List<int> LinkIds = new List<int>();

            if (!string.IsNullOrEmpty(_NodeIds))
            {
                NodeIds = ConvertHelper.ToObject<List<int>>(_NodeIds);
                Flow.processors.RemoveAll((node) => NodeIds.Contains(node.id));
            }
            if (!string.IsNullOrEmpty(_LinkIds))
            {
                LinkIds = ConvertHelper.ToObject<List<int>>(_LinkIds);
                Flow.connections.RemoveAll((node) => LinkIds.Contains(node.id));
            }

            FlowProcessor.UpdateFlow(Flow);
            return Flow.ToJson(new[] { "Children", "Parents" });
        }

        /// <summary>
        /// 创建节点连线
        /// 
        ///  processGroup.connections = [{ id: 1111221, source: source.id, sourcePort: sourcePort, target: target.id }]
        /// </summary>
        /// <param name="FolwId"></param>
        /// <param name="SourceNodeId"></param>
        /// <param name="TargetNodeId"></param>
        /// <param name="SourcePort"></param>
        /// <returns></returns>

        internal string CreateConnection(ConnectionDTO Connection)
        {
            AppData.RemoveOpenFlow(Connection.FlowId);
            FlowRoot Flow = GetFlow(Connection.FlowId);
            Flow.nodeNumber = Flow.nodeNumber + 1;
            Connection NewLine = new Connection { source = Connection.SourceNodeId, target = Connection.TargetNodeId, sourcePort = Connection.SourcePort };
            if (Flow.connections == null || Flow.connections.Count <= 0)
            {
                NewLine.id = Flow.nodeNumber;
                Flow.connections = new List<Connection> { NewLine };
            }
            else
            {
                bool IsAdd = false;
                foreach (Connection item in Flow.connections)
                {
                    IsAdd = item.source == Connection.SourceNodeId && item.target == Connection.TargetNodeId;
                    if (IsAdd)
                    {
                        break;
                    }
                }
                if (!IsAdd)
                {
                    NewLine.id = Flow.nodeNumber;
                    Close = false;
                    if (!CheckClosedLine(Flow, NewLine, NewLine))
                    {
                        Flow.connections.Add(NewLine);
                    }
                }
            }
            UpdateFlow(Flow);
            return Flow.ToJson(new[] { "Children", "Parents" });
        }

        /// <summary>
        /// 克隆节点
        /// </summary>
        /// <param name="FolwId"></param>
        /// <param name="NodeIds"></param>
        /// <param name="Connections"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        internal string CloneNode(long SourceFlowId, long FlowId, string NodeIds, List<Connection> Connections)
        {
            if (string.IsNullOrEmpty(NodeIds))
            {
                throw new Exception("复制节点异常");
            }
            AppData.RemoveOpenFlow(FlowId);
            FlowRoot SourceFlow = GetFlow(SourceFlowId);
            FlowRoot TrigerFlow = GetFlow(FlowId);

            List<NodeProcessor> CN = SourceFlow.processors.Where((n) => NodeIds.Contains(n.id.ToString())).ToList();
            List<NodeProcessor> NewNodeTemp = new List<NodeProcessor>();

            long _NodeId = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            for (int i = 0; i < CN.Count; i++)
            {
                NodeProcessor CloneTagter = CN[i].Copy();
                CloneTagter.CloneNodeTempId = CloneTagter.id;
                ++_NodeId;

                CloneTagter.rect.x = CN[i].rect.x + 20;
                CloneTagter.rect.y = CN[i].rect.y + 20;
                CloneTagter.id = FlowNode.GeneratedId(TrigerFlow);

                TrigerFlow.processors.Add(CloneTagter);

                NewNodeTemp.Add(CloneTagter);
            }

            long _ConnectionId = _NodeId + NewNodeTemp.Count + 100;
            for (int i = 0; i < Connections.Count; i++)
            {
                Connection Conn = Connections[i];

                ++_ConnectionId;
                Conn.id = TrigerFlow.connections.Count + 1;
                NewNodeTemp.ForEach(node =>
                {
                    if (node.CloneNodeTempId == Conn.source)
                    {
                        Conn.source = node.id;
                    }
                    if (node.CloneNodeTempId == Conn.target)
                    {
                        Conn.target = node.id;
                    }
                });

                TrigerFlow.connections.Add(Conn);
            }

            UpdateFlow(TrigerFlow);
            return TrigerFlow.ToJson(new[] { "Children", "Parents" });
        }

        /// <summary>
        /// 配置节点信息时，更新节点
        /// </summary>
        /// <param name="FlowId"></param>
        /// <param name="NodeId"></param>
        /// <param name="nodeItemParamsJson"></param>
        /// <param name="IsPreCompiling"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        internal FlowRoot UpdateFlowNodeParams(UpdateNodeParamDTO UpdateNodeParam)
        {
            NodeInputParam Param = ConvertHelper.ToObject<NodeInputParam>(UpdateNodeParam.NodeItemParamsJson);
            if (Param == null)
            {
                throw new Exception("节点数据异常");
            }
            AppData.RemoveOpenFlow(UpdateNodeParam.FlowId);
            FlowRoot Flow = FlowProcessor.GetFlow(UpdateNodeParam.FlowId);

            int Index = Flow.processors.FindIndex((no) => no.id == UpdateNodeParam.NodeId);
            if (Index < 0)
            {
                throw new Exception("流程找不到节点");
            }
            NodeProcessor node = Flow.processors[Index];
            LoggerService.UpdateDataLog(node.NodeInputParam, Param, "");
            node.NodeInputParam = Param;
            node.name = UpdateNodeParam.NodeName;
            node.NodeTimeOut = UpdateNodeParam.NodeTimeOut;
            SetNodeOutParam(node);
            if (UpdateNodeParam.IsPreCompiling)
            {
                node.IsPreCompiling = true;
                LogicProcessor.Run(node, node.NodeInputParam);
            }
            FlowProcessor.UpdateFlow(Flow);
            // Flow.ToJson(new[] { "Children", "Parents" });
            return Flow;
        }

        /// <summary>
        /// 设置节点的可输出参数
        /// </summary>
        /// <param name="flow"></param>
        /// <param name="param"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void SetNodeOutParam(NodeProcessor node)
        {
            List<NodeOutParam> nodeOutParams = new List<NodeOutParam>();
            if (node.nodeType == NodeTypeEnum.PLC_READ)
            {
                NodeOutParam Out = new NodeOutParam();
                Out.ParamName = NodeOutParamNameEnum.DEVICE_READ_RESULT.ToString();

                nodeOutParams.Add(Out);
            }
            if (node.nodeType == NodeTypeEnum.MES_MiFindCustomAndSfcData)
            {
                NodeOutParam Out = new NodeOutParam();
                Out.ParamName = NodeOutParamNameEnum.MES_MiFindCustomAndSfcData_RESULT.ToString();
                Out.ValueType = "object";

                nodeOutParams.Add(Out);
            }
        }

        bool Close = false;
        public bool CheckClosedLine(FlowRoot Flow, Connection Line, Connection NewLine)
        {
            foreach (Connection Item in Flow.connections)
            {
                if (Close)
                {
                    break;
                }
                if (Line.source == Item.target)
                {
                    if (Item.source == NewLine.target)
                    {
                        Close = true;
                        JavaScriptEvent.Send(JavaScriptEventEnum.GLOBAL_MESSAGE_NOTICE, "无法创建闭环流程");
                    }
                    else
                    {
                        CheckClosedLine(Flow, Item, NewLine);
                    }
                }
            }
            return Close;
        }

        internal void UpdateFlowNodeParam(long FlowId, int NodeId, string Param, int Value)
        {
            FlowRoot Flow = FlowProcessor.GetFlow(FlowId);
            foreach (NodeProcessor Node in Flow.processors)
            {
                if (Node.id == NodeId && Param == "enable")
                {
                    Node.enable = Value;
                    Node.style.backgroundColor = Value == 1 ? "#0b9b0b" : "#4d4d4d";
                    FlowProcessor.UpdateFlow(Flow);
                    break;
                }
            }
        }
    }
}
